#include<my_header.h>
//单条件变量实现生产者消费者模型
typedef struct Node_s{
    int val;
    struct Node_s* next;
}Node_t;

typedef struct List_s{
    int size;
    Node_t* head;
    Node_t* tail;
}List_t;

typedef struct Shared_s{
    int flag;
    pthread_cond_t cond;
    pthread_mutex_t mutex;
    List_t* list;
}Shared_t;

void *head_del(void* arg){
    sleep(5);
    Shared_t* share=(Shared_t*) arg;
    // while (share->list->size>=0&&share->list->size<=10)//防止越界生产访问
    while(1)
    {
        pthread_mutex_lock(&share->mutex);
        while(share->flag==1||share->list->size==0){
            pthread_cond_wait(&share->cond,&share->mutex);
        }
        share->flag=1;
        
        Node_t* cur=share->list->head;
        if(share->list->size==1){
            share->list->tail=NULL;
            share->list->head = NULL;
        }else{
            share->list->head=cur->next;
        }
        printf("%lu消费者正在消费%d号商品\n",pthread_self(),cur->val);
        free(cur);
        share->list->size--;
        sleep(1);
        printf("消费完成\n");
        share->flag=0;
        pthread_cond_broadcast(&share->cond);
        pthread_mutex_unlock(&share->mutex);
        sleep(1);   //防止此线程一直抢占资源。
    }
    return NULL;
}

void *tail_ins(void* arg){
    Shared_t* share=(Shared_t*) arg;
    // while(share->list->size>=0 && share->list->size<=10){ //防止越界生产访问
    while(1){
        pthread_mutex_lock(&share->mutex);
       
        while(share->flag||share->list->size==10){
            pthread_cond_wait(&share->cond,&share->mutex);
        }
        share->flag=1;
        Node_t* node = (Node_t*)calloc(1, sizeof(Node_t));
        node->val = rand()%1000+1;
        node->next = NULL;
        printf("%lu生产者正在生产%d号商品\n",pthread_self(),node->val);
        if(share->list->size==0){
            share->list->head=node;
            share->list->tail=node;
        }else{
            //尾插法错误,以及修改
            share->list->tail->next=node;
            share->list->tail=node;
        }
        share->list->size++;
        sleep(3);
        printf("生产者生产完成\n");
        share->flag=0;
        pthread_cond_broadcast(&share->cond);
        pthread_mutex_unlock(&share->mutex);
        sleep(3);   //防止此线程一直抢占资源。
    }
    
    return NULL;
}

int main(){
    Shared_t* share=(Shared_t*) calloc(1,sizeof(Shared_t));
    share->list=(List_t*) calloc(1,sizeof(List_t));
    share->list->size=0;
    share->list->head=NULL;
    share->list->tail=NULL;
    share->flag=0;
    pthread_cond_init(&share->cond,NULL);
    pthread_mutex_init(&share->mutex,NULL);
    
    srand(time(0));
    for(int i=0;i<8;i++){
        Node_t* node= (Node_t*) calloc(1,sizeof(Node_t));
        node->val=rand()%1000+1;
        node->next=NULL;
        if(share->list->size==0){
            share->list->head=node;
            share->list->tail=node;
        }else{
            node->next=share->list->head;
            share->list->head=node;
        }
        share->list->size++;
    }

    pthread_t sell_arr[3],cons_arr[2];
    for(int i=0;i<3;i++){
        pthread_create(&sell_arr[i],NULL,tail_ins,share);
    }
    for(int i=0;i<2;i++){
        pthread_create(&cons_arr[i],NULL,head_del,share);
    }
    
   while(1){
    sleep(10);
   }
    // 回收条件变量
    pthread_exit(NULL);     // 回收主线程
    pthread_cond_destroy(&share->cond);
    pthread_mutex_destroy(&share->mutex);
    Node_t* cur=share->list->head;
    while (cur){
        Node_t* tmp=cur;
        cur=cur->next;
        free(tmp);
    }
    free(share->list);
    free(share);
    printf("资源回收完成\n");
    return 0;
}